#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "system/imp_alloc.h"
#include "ncubuf.h"
#include "common.h"
#include <imp/imp_log.h>
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
#define TAG "NCUBUF"
IMPAlloc *ncu_buf_alloc(uint32_t size, char *owner)
{
	int ret = -1;
	IMPAlloc *alloc = malloc(sizeof(IMPAlloc));
	if (NULL == alloc) {
		printf("error(%s,%d): maloc err\n", __func__, __LINE__);
		return NULL;
	}
	ret = IMP_Alloc(alloc, size, owner);
	if (0 != ret) {
		printf("error(%s,%d): IMP_Alloc\n", __func__, __LINE__);
		return NULL;
	}
	return alloc;
}

int ncu_buf_free(IMPAlloc *alloc, uint32_t vaddr)
{
	IMP_Free(alloc, (void *)vaddr);
	free(alloc);
	return 0;
}

int ncu_all_buf_alloc(ncu_info *info)
{
	uint32_t size = 0;
	uint32_t w = info->src_attr.frm_w;
	uint32_t h = info->src_attr.frm_h;
	IMPAlloc *alloc  = NULL;

	//cur buf
	size = w*h*3/2;
#if 0
	alloc = ncu_buf_alloc(size);
	info->cur_buf.handle = (uint32_t)alloc;
	info->cur_buf.bufaddr = alloc->info.vaddr;
	info->cur_buf.bufsize = size;
	info->cur_buf.y_addr = alloc->info.vaddr;
	info->cur_buf.uv_addr = alloc->info.vaddr+w*h;
	info->cur_buf.y_paddr = alloc->info.paddr;
	info->cur_buf.uv_paddr = alloc->info.paddr+w*h;
#endif

	//ref0 buf
	alloc = ncu_buf_alloc(size, "ncuref");
	info->ref_buf0.handle = (uint32_t)alloc;
	info->ref_buf0.bufaddr = alloc->info.vaddr;
	info->ref_buf0.bufsize = size;
	info->ref_buf0.y_addr = alloc->info.vaddr;
	info->ref_buf0.uv_addr = alloc->info.vaddr+w*h;
	info->ref_buf0.y_paddr = alloc->info.paddr;
	info->ref_buf0.uv_paddr = alloc->info.paddr+w*h;

	//ref1 buf
#if 0
	alloc = ncu_buf_alloc(size);
	info->ref_buf1.handle = (uint32_t)alloc;
	info->ref_buf1.bufaddr = alloc->info.vaddr;
	info->ref_buf1.bufsize = size;
	info->ref_buf1.y_addr = alloc->info.vaddr;
	info->ref_buf1.uv_addr = alloc->info.vaddr+w*h;
	info->ref_buf1.y_paddr = alloc->info.paddr;
	info->ref_buf1.uv_paddr = alloc->info.paddr+w*h;
#endif

	//sta
#if 0
	uint32_t yoffset = 0;
	uint32_t uoffset = 0;
	uint32_t voffset = 0;
	uint32_t usize = 0;
	uint32_t vsize = 0;
#endif
	uint32_t ysize = 0;

	ysize = info->sta_attr.sta_y_stride*(DIV_ROUND_UP(info->src_attr.frm_h, 28)+1);
#if 0
	usize = info->sta_attr.sta_uv_stride*(DIV_ROUND_UP(info->src_attr.frm_h/2, 8)+1);
	vsize = usize;
#endif

#if 0
	uoffset = yoffset+ysize;
	uoffset = ALLIGN(uoffset, 256);
	voffset = uoffset+usize;
	voffset = ALLIGN(voffset, 256);
	size = voffset+vsize;
#endif
	info->sta_buf.cnt = 50;
	size = ysize*info->sta_buf.cnt;
	alloc = ncu_buf_alloc(size, "ncusta");
	info->sta_buf.handle = (uint32_t)alloc;
	info->sta_buf.bufaddr = alloc->info.vaddr;
	info->sta_buf.bufsize = size;
	info->sta_buf.ysize = ysize;
	info->sta_buf.y_addr = alloc->info.vaddr;
#if 0
	info->sta_buf.u_addr = alloc->info.vaddr+uoffset;
	info->sta_buf.v_addr = alloc->info.vaddr+voffset;
#endif
	info->sta_buf.y_paddr = alloc->info.paddr;
#if 0
	info->sta_buf.u_paddr = alloc->info.paddr+uoffset;
	info->sta_buf.v_paddr = alloc->info.paddr+voffset;
#endif

	IMP_LOG_INFO(TAG, "sta paddr:%p vaddr:%p \n", info->sta_buf.y_paddr, info->sta_buf.y_addr);
	//do not use psn
	//psn
#if 0
	yoffset = 0;
	uoffset = 0;
	voffset = 0;
	ysize = 0;
	usize = 0;
	vsize = 0;

	ysize = info->psn_attr.psn_y_stride*h;
	usize = info->psn_attr.psn_uv_stride*h;
	vsize = info->psn_attr.psn_uv_stride*h;

	uoffset = yoffset+ysize;
	uoffset = ALLIGN(uoffset, 256);
	voffset = uoffset+usize;
	voffset = ALLIGN(voffset, 256);
	size = voffset+vsize;
	alloc = ncu_buf_alloc(size);
	info->psn_buf.handle = (uint32_t)alloc;
	info->psn_buf.bufaddr = alloc->info.vaddr;
	info->psn_buf.bufsize = size;
	info->psn_buf.y_addr = alloc->info.vaddr;
	info->psn_buf.u_addr = alloc->info.vaddr+uoffset;
	info->psn_buf.v_addr = alloc->info.vaddr+voffset;
	info->psn_buf.y_paddr = alloc->info.paddr;
	info->psn_buf.u_paddr = alloc->info.paddr+uoffset;
	info->psn_buf.v_paddr = alloc->info.paddr+voffset;
#endif
	return 0;
}

int ncu_all_buf_free(ncu_info *info)
{
	//ncu_buf_free((void *)info->cur_buf.handle, info->cur_buf.bufaddr);
	ncu_buf_free((void *)info->ref_buf0.handle, info->ref_buf0.bufaddr);
	//ncu_buf_free((void *)info->ref_buf1.handle, info->ref_buf1.bufaddr);
	ncu_buf_free((void *)info->sta_buf.handle, info->sta_buf.bufaddr);
	//ncu_buf_free((void *)info->psn_buf.handle, info->psn_buf.bufaddr);
	return 0;
}
